﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Valentia.Kinection.Configuration;
using Valentia.Kinection.DataTypes;
using System.Text.RegularExpressions;

namespace Valentia.Kinection.Configuration.Manager
{
    /// <summary>
    /// User control used to add/update kinect device
    /// </summary>
    public partial class KinectDeviceControl : UserControl
    {
        #region Declarations
        /// <summary>
        /// Device ID
        /// </summary>
        private int kinectDeviceID = -1;
        #endregion

        #region Constructor
        /// <summary>
        /// Constructor
        /// </summary>
        public KinectDeviceControl()
        {
            InitializeComponent();
            InitializeControls();           
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Set the form control values with the provided kinect device info
        /// </summary>
        /// <param name="kinectDevice">Kinect device</param>
        public void InitializeWithKinectDeviceData(KinectDevice kinectDevice)
        {            
            this.kinectDeviceID = kinectDevice.ID;

            txtDeviceName.Text = kinectDevice.KinectDeviceName;
            chkActive.Checked = kinectDevice.Active;
            chkVideoStream.Checked = kinectDevice.GenerateVideoStream;
            chkDepthStream.Checked = kinectDevice.GenerateDepthStream;
            chkSkeletonStream.Checked = kinectDevice.GenerateSkeletonStream;
            nudSkeletonSmoothing.Value = Decimal.Parse(kinectDevice.SkeletonSmoothing.ToString());
            nudSksletonCorrection.Value = Decimal.Parse(kinectDevice.SkeletonCorrection.ToString());
            nudPrediction.Value = Decimal.Parse(kinectDevice.SkeletonPrediction.ToString());
            nudJitter.Value = Decimal.Parse(kinectDevice.SkeletonJitterRadius.ToString());

            cmbVideoResoloution.Text = kinectDevice.KinectVideoResoloution.ToString();
            cmbDepthResoloution.Text = kinectDevice.KinectDepthResoloution.ToString();

            btnSaveUpdate.Text = "   Update";
            txtDeviceName.ReadOnly = true;
        }
        #endregion

        #region Private Methods
        /// <summary>
        /// Intializes form controls with defualt values
        /// </summary>
        private void InitializeControls()
        {
            String[] colorFormats = Enum.GetNames(typeof(KinectColorImageFormat));
            foreach (String resolution in colorFormats)
            {
                if (resolution.Equals(KinectColorImageFormat.Undefined.ToString())) continue;

                this.cmbVideoResoloution.Items.Add(resolution);
            }

            String[] depthFormats = Enum.GetNames(typeof(KinectDepthImageFormat));
            foreach (String resolution in colorFormats)
            {
                if (resolution.Equals(KinectDepthImageFormat.Undefined.ToString())) continue;

                this.cmbDepthResoloution.Items.Add(resolution);
            }

            this.cmbVideoResoloution.SelectedIndex = 0;
            this.cmbDepthResoloution.SelectedIndex = 0;
        }
       
        /// <summary>
        /// Validates the kinect device data to be saved
        /// </summary>
        /// <returns>True/False : kinect device data is valid</returns>
        private bool IsValidData()
        {
            errProvider.Clear();
            if (txtDeviceName.Text.Trim().Equals(string.Empty))
            {
                errProvider.SetError(txtDeviceName, "Please provide device name");
                txtDeviceName.Focus();
                return false;
            }

            if (!Regex.Match(txtDeviceName.Text, "^[a-zA-Z0-9 ]+$").Success)
            {
                errProvider.SetError(txtDeviceName, "Device name must be alphanumeric");
                txtDeviceName.Focus();
                return false;
            }

            return true;
        }
        #endregion

        #region Form control events
        /// <summary>
        /// Occurs when Save/Update button is clicked
        /// </summary>
        /// <param name="sender">Sender</param>
        /// <param name="e">Event Args</param>
        private void btnSaveUpdate_Click(object sender, EventArgs e)
        {
            if (!IsValidData()) return;

            if (this.kinectDeviceID == -1)
            {
                ConfigurationHelper.SaveKinectDevice(
                    txtDeviceName.Text, txtDeviceName.Text, chkActive.Checked, chkVideoStream.Checked, chkDepthStream.Checked, chkSkeletonStream.Checked,
                    Double.Parse(nudSkeletonSmoothing.Value.ToString()), Double.Parse(nudSksletonCorrection.Value.ToString()),
                    Double.Parse(nudPrediction.Value.ToString()), Double.Parse(nudJitter.Value.ToString()), Double.Parse(nudMaxDeviation.Value.ToString()),
                    (KinectColorImageFormat)Enum.Parse(typeof(KinectColorImageFormat), cmbVideoResoloution.SelectedItem.ToString()),
                    (KinectDepthImageFormat)Enum.Parse(typeof(KinectDepthImageFormat), cmbDepthResoloution.SelectedItem.ToString()));
            }
            else
            {
                using (ConfigDatabaseEntities context = ConfigurationHelper.GetContext())
                {
                    KinectDevice kinectDevice = ConfigurationHelper.GetKinectDeviceByName(context, txtDeviceName.Text);

                    if (kinectDevice != null)
                    {
                        kinectDevice.Active = chkActive.Checked;
                        kinectDevice.GenerateVideoStream = chkVideoStream.Checked;
                        kinectDevice.GenerateDepthStream = chkDepthStream.Checked;
                        kinectDevice.GenerateSkeletonStream = chkSkeletonStream.Checked;
                        kinectDevice.SkeletonSmoothing = Double.Parse(nudSkeletonSmoothing.Value.ToString());
                        kinectDevice.SkeletonCorrection = Double.Parse(nudSksletonCorrection.Value.ToString());
                        kinectDevice.SkeletonPrediction = Double.Parse(nudPrediction.Value.ToString());
                        kinectDevice.SkeletonJitterRadius = Double.Parse(nudJitter.Value.ToString());
                        kinectDevice.SkeletonMaxDeviationRadius = Double.Parse(nudMaxDeviation.Value.ToString());

                        kinectDevice.KinectVideoResoloution = (KinectColorImageFormat)Enum.Parse(typeof(KinectColorImageFormat), cmbVideoResoloution.SelectedItem.ToString());
                        kinectDevice.KinectDepthResoloution = (KinectDepthImageFormat)Enum.Parse(typeof(KinectDepthImageFormat), cmbDepthResoloution.SelectedItem.ToString());
                        
                        context.SaveChanges();
                    }
                }
            }
            ((Form)(this.Parent)).Close();
        }

        /// <summary>
        /// Occurs when Cancel button is clicked
        /// </summary>
        /// <param name="sender">Sender</param>
        /// <param name="e">Event Args</param>
        private void btnCancel_Click(object sender, EventArgs e) { ((Form)(this.Parent)).Close(); }
        #endregion
    }
}

